#include"yi_shell.h"
#include"stdio.h"
#include"string.h"
#include"syscall.h"
#include"file.h"
#include"buildin_cmd.h"
#include"string.h"
#include"file.h"

#define MAX_CMD_CNT 128
#define MAX_ARG_CNT 8

static char cmd_line[MAX_PATH_LEN];

char cwd[MAX_CMD_CNT]={"/"};

char abs_path_buffer[MAX_PATH_LEN];

char* argv[MAX_ARG_CNT];

static int32_t parse_cmd(char token,char** argv);
static void read_cmd(void);
static void shell_prompt(void);

static void shell_prompt(void){
	printf("[master_yi@loclhost %s]#",cwd);
}

static void read_cmd(){
	char* pos=cmd_line;
	while(pos-cmd_line<MAX_CMD_CNT && read(stdin_no,pos,1)!=-1){
		switch(*pos){
			case '\r':
			case '\n':
				*pos=0;
				putchar('\n');
				return;
			case '\b':
				if(cmd_line[0]!='\b'){
					pos--;
					putchar('\b');
				}
				break;
			//<ctrl>+l clear screen
			case 'l'-'a':
				*pos=0;
				clear();
				shell_prompt();
				printf("%s",cmd_line);	
				break;
			//<ctrl>+u clear input cmd
			case 'u'-'a':
				while(pos!=cmd_line){
					putchar('\b');
					*pos=0;
					pos--;
				}
				break;
			default:
				putchar(*pos);
				pos++;
				break;
		}
	}
}

int32_t parse_cmd(char token,char** argv){
	char* p=cmd_line;
	uint32_t idx=0;
	uint8_t argc=0;
	while(idx<MAX_CMD_CNT && *p){
		while(*(p+idx)==token){
			idx++;
			if(idx==MAX_CMD_CNT){
				goto ret;
			}
		}
		*(argv+argc)=p+idx++;
		while(idx<MAX_CMD_CNT && *(p+idx)!=token){
			idx++;
		}
		argc++;
		*(p+idx++)=0;
		if(idx==MAX_CMD_CNT){
			return argc;
		}
		if(argc>MAX_ARG_CNT){
			return -1;
		}
	}
ret:
	return !argc ? -1 : argc;
}
#define SHELL_TOKEN ' '
void yi_shell(void){
	int32_t argc;
	int32_t status;
	clear();
	while(1){
		shell_prompt();
		memset(cmd_line,0,MAX_CMD_CNT);		
		read_cmd();
		if(!cmd_line[0]){
			continue;
		}

		if((argc=parse_cmd(SHELL_TOKEN,argv))<0){
			printf("bad command\n");
		}else{
			if(!exec_buildin_cmd(argc,argv)){
				struct stat st={0,0,FT_UNKNOWN};
				abs_path(abs_path_buffer,argv[0]);
				if(stat(abs_path_buffer,&st)<0){
					printf("%s command not found\n",argv[0]);
				}else{
					pid_t pid=fork();
					if(pid<0){
						printf("fork error\n");	
					}else if(!pid){
						//child process run here
						if(execv(argv[0],argv)<0){
							printf("execute %s failed\n",argv[0]);
						}
					}else{
						//wait external process finish
						wait(&status);
					}
				}
			}
		}
	}
}
